﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MiniIOC.IOCLIbs
{
    public class ServiceCollection : Collection<ServiceDescriptor>, IServiceCollection
    {
        private readonly ServiceDescriptorEqualityComparer _serviceDescriptorEqualityComparer;
        public ServiceCollection()
        {
            _serviceDescriptorEqualityComparer = new ServiceDescriptorEqualityComparer();
        }

        public void AddTransient<TService, TImplement>()
            where TService : class
            where TImplement : TService
        {
            AddTransient(typeof(TService), typeof(TImplement));
        }

        public void AddTransient(Type seviceType, Type implementType)
        {
            var discriptor = new ServiceDescriptor
            {
                Lifetime = ServiceLifetime.Transient,
                ServiceType = seviceType,
                ImplementationType = implementType
            };
            TryAdd(discriptor);
        }

        public void AddScoped<TService, TImplement>()
            where TService : class
            where TImplement : TService
        {
            AddScoped(typeof(TService), typeof(TImplement));
        }

        public void AddScoped(Type seviceType, Type implementType)
        {
            var discriptor = new ServiceDescriptor
            {
                Lifetime = ServiceLifetime.Scoped,
                ServiceType = seviceType,
                ImplementationType = implementType
            };
            TryAdd(discriptor);
        }

        public void AddSington<TService, TImplement>()
            where TService : class
            where TImplement : TService
        {
            AddSington(typeof(TService), typeof(TImplement));
        }

        public void AddSington<TService>(object instance)
            where TService : class
        {
            AddSington(typeof(TService), instance.GetType(), instance);
        }

        public void AddSington(Type seviceType, Type implementType)
        {
            AddSington(seviceType, implementType, null);
        }

        public void AddSington(Type seviceType, Type implementType, object? instacne)
        {
            var discriptor = new ServiceDescriptor()
            {
                Lifetime = ServiceLifetime.Singleton,
                ServiceType = seviceType,
                ImplementationType = implementType,
                ImplementationInstance = instacne
            };
            TryAdd(discriptor);
        }

        private bool TryAdd(ServiceDescriptor serviceDescriptor)
        {
            if (this.Contains(serviceDescriptor, _serviceDescriptorEqualityComparer)) return false;

            this.Add(serviceDescriptor);
            return true;
        }
    }
}
